Skip to content

feat(protect): DNS-rebinding resistance for egress (Node http path) - #89

Merged
patchstackdave merged 1 commit into
mainfrom
feat/protect-egress-dns-rebinding
Jul 16, 2026
Merged

feat(protect): DNS-rebinding resistance for egress (Node http path)#89
patchstackdave merged 1 commit into
mainfrom
feat/protect-egress-dns-rebinding

Conversation

@patchstackdave

Copy link
Copy Markdown
Contributor

The egress guard screened outbound calls by hostname, so a name that passes the check but resolves to an internal/metadata IP (DNS rebinding, or just a hostname pointing inward) slipped through.

On the Node http/https path, inject a screening DNS lookup into the request options:

  • resolve the hostname, run each resolved address through the same egress predicate (so internal_host rules + the allowlist apply to the resolved IP too),
  • block if any is disallowed, and pin the connection to the vetted resolution — closing the time-of-check/time-of-use gap.

Only for real hostnames (literal IPs already covered by the sync check). Default on via screenDns (disable with screenDns: false); needs node:dns/net, so it's a no-op on edge runtimes (hostname rules still apply). Fail-open: a resolver/injection error proceeds unscreened rather than breaking the request. The resolver is injectable for tests.

The fetch/undici path is intentionally deferred (the fiddly part — needs a custom dispatcher to pin) — this is the easy, complete Node-path fix.

+5 tests. 495 pass, typecheck (incl. template check) + build clean.

@coderbuds

coderbuds Bot commented Jul 16, 2026

Copy link
Copy Markdown

DNS-rebinding guard is well-designed and thoroughly tested.

🎯 Quality: 100% Elite · 📦 Size: Medium

📈 This month: Your 38th PR — above team average · Averaging Excellent

See how your team is trending →

The egress guard screened outbound calls by hostname, so a name that passes the check but resolves
to an internal/metadata IP (DNS rebinding, or just a hostname pointing inward) slipped through.

On the Node http/https path, inject a screening DNS `lookup` into the request options: resolve the
hostname, run each resolved address through the same egress predicate (so `internal_host` rules +
allowlist apply to the IP too), block if any is disallowed, and pin the connection to the vetted
resolution — closing the time-of-check/time-of-use gap. Only for real hostnames (literal IPs are
already covered by the sync check). Default on via `screenDns` (disable with `screenDns: false`);
needs node:dns/net, so it's a no-op on edge runtimes, where hostname rules still apply. Fail-open:
a resolver or injection error proceeds unscreened rather than breaking the request. `lookup` is
injectable for tests. The fetch/undici path is intentionally left for a follow-up.

+5 tests, 495 total, typecheck (incl. template check) + build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@patchstackdave
patchstackdave force-pushed the feat/protect-egress-dns-rebinding branch from a241861 to 80e78d8 Compare July 16, 2026 06:52
@patchstackdave

Copy link
Copy Markdown
Contributor Author

/review

@patchstackdave
patchstackdave merged commit 90e8c5b into main Jul 16, 2026
4 checks passed
@patchstackdave
patchstackdave deleted the feat/protect-egress-dns-rebinding branch July 16, 2026 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants